#include "CSprite.h"
#include <cstdio>

#include <SDL_image.h>

#include "myexception.h"

using namespace std;

int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a)
{
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	Uint16 alpha_offset = 0;
#else
	Uint16 alpha_offset = 3;
#endif
	Uint16 i, j;
	
	/* Check if we have a 32bit surface */
	if ( (src) && (src->format) && (src->format->BytesPerPixel==4) ) {
	 /* Lock and process */
  	 if ( SDL_LockSurface(src) == 0 ) {
	  Uint8 *pixels = (Uint8 *)src->pixels;
	  Uint16 row_skip = (src->pitch - (4*src->w));
	  pixels += alpha_offset;
	  for ( i=0; i<src->h; i++ ) {
		 for ( j=0; j<src->w; j++  ) {
		  *pixels *= (float)a / 256.0;
		  pixels += 4;
		 }
		 pixels += row_skip;
          }
          SDL_UnlockSurface(src);
	 }
	 return 1;
        } else {
         return 0;
        } 
}


SDL_Rect GetClipRect(SDL_Surface* surface)
{
	if (surface->format->BytesPerPixel != 4)
		throw MyException("Bad surface BPP != 32");

	if (SDL_MUSTLOCK(surface))
		if (SDL_LockSurface(surface) < 0)
			throw MyException("Can't lock surface");

	int min_x = surface->w;
	int min_y = surface->h;
	int max_x = 0;
	int max_y = 0;

	// find min/max x
	for (int y = 0; y < surface->h; ++y)
		for (int x = 0; x < surface->w; ++x)
		{
			Uint8 r,g,b,a;
			Uint32 *color = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
			SDL_GetRGBA(*color, surface->format, &r, &g, &b, &a);
			if (a != 0)
			{
				if (min_x > x)
					min_x = x;

				if (max_x < x)
					max_x = x;
			}
		}

	// find min/max y
	for (int y = 0; y < surface->h; ++y)
		for (int x = 0; x < surface->w; ++x)
		{
			Uint8 r,g,b,a;
			Uint32 *color = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
			SDL_GetRGBA(*color, surface->format, &r, &g, &b, &a);
			if (a != 0)
			{
				if (min_y > y)
					min_y = y;

				if (max_y < y)
					max_y = y;

				continue;
			}
		}

	if (SDL_MUSTLOCK(surface))
        SDL_UnlockSurface(surface);

	SDL_Rect r;
	r.x = min_x;
	r.y = min_y;
	r.w = max_x - min_x;
	r.h = max_y - min_y;

	return r;
}

CSprite::CSprite(const string& fname)
: Surface(0)
, FromFile(true)
, PosX(0)
, PosY(0)
{
	// fprintf(stderr, "Load sprite from %s file.\n", fname.c_str());
	Surface = IMG_Load(fname.c_str());

	if (fname == "Content/Character Boy.png")
		SDL_gfxSetAlpha(Surface, 100);
	
	if (!Surface)
		throw MyException("Couldn't load sprite");

	Rect = GetClipRect(Surface);
}

CSprite::CSprite(SDL_Surface* surface, const SDL_Rect& rect, const SDL_Rect& dest_rect)
: Surface(surface)
, Rect(rect)
, PosX(dest_rect.x)
, PosY(dest_rect.y)
{
}

CSprite::~CSprite()
{
	// fprintf(stderr, "Free sprite\n");
	if (Surface && FromFile)
		SDL_FreeSurface(Surface);
}

SDL_Surface* CSprite::GetSurface() const
{
	return Surface;
}

const SDL_Rect& CSprite::GetRect() const
{
	return Rect;
}
